import subprocess
import rrd_base
import re
import time

import color

try:
    from pyrrd.rrd import DataSource, RRA, RRD
    from pyrrd.graph import DEF, CDEF, VDEF
    from pyrrd.graph import LINE, AREA, GPRINT
    from pyrrd.graph import ColorAttributes, Graph
except:
    print "Couldn't load required modules. You probably need to install it with:"
    sys.exit('sudo apt-get install python-pyrrd python-pysnmp4')

class RrdPing(rrd_base.RrdBase):
    def __init__(self, domain, name):
        super(RrdPing,self).__init__(domain=domain, group="net", instance=name)

    def create_file(self):
        dataSources = []
        dataSources.append(DataSource( dsName='rtt', dsType='GAUGE', heartbeat=self.heartbeat()))

        roundRobinArchives = []
        for func in ['AVERAGE', 'MAX', 'MIN']:
            for step,row in self.rra_pattern():
                roundRobinArchives.append(RRA(cf=func, xff=0.5, steps=step, rows=row))

        self.myRRD = RRD(self.filename, ds=dataSources, rra=roundRobinArchives, step=self.data_step())
        self.myRRD.create()

    def update(self):
        ping = subprocess.Popen(["/bin/ping", "-c5", "-W", "1", "-i", ".2", "8.8.8.8"], shell=False, stdout=subprocess.PIPE)
        data = ping.communicate()[0]
        for line in data.split("\n"):
            if re.search("rtt ", line):
                words = re.sub("[/]", " ", line).split()
                self.myRRD.bufferValue(int(round(time.time())), float(words[7]) / 1000.0)
                self.myRRD.update()
                break
            if re.search("100% packet loss", line):
                self.myRRD.bufferValue(int(round(time.time())), 1)
                self.myRRD.update()
                break

    def graph(self):
        d_avg   =  DEF(rrdfile=self.myRRD.filename, vname='rtt', cdef="AVERAGE", dsName='rtt')
        d_max   =  DEF(rrdfile=self.myRRD.filename, vname='rtt_max', cdef="MAX", dsName='rtt')
        d_min   =  DEF(rrdfile=self.myRRD.filename, vname='rtt_min', cdef="MIN", dsName='rtt')
        v_peak  = VDEF(vname="v0",      rpn="{0},MAXIMUM".format(d_max.vname))
        v_avg   = VDEF(vname="v1",      rpn="{0},AVERAGE".format(d_avg.vname))
        v_nadir = VDEF(vname="v2",      rpn="{0},MINIMUM".format(d_min.vname))
        area_0  = AREA(defObj=d_avg,      color=color.RGBA['green'])
        l_max   = LINE(1, defObj=d_max,   color=color.RGBA['red'])
        l_min   = LINE(1, defObj=d_min,   color=color.RGBA['blue'])
        l_peak  = LINE(1, defObj=v_peak,  color=color.RGBA["red"])
        l_avg   = LINE(1, defObj=v_avg,   color=color.RGBA["green"])
        l_nadir = LINE(1, defObj=v_nadir, color=color.RGBA["blue"])
        p_peak  = GPRINT(v_peak,  "Peak %.0lf%sS")
        p_nadir = GPRINT(v_nadir, "Nadir %.0lf%sS")
        p_avg   = GPRINT(v_avg,   "Avg %.0lf%sS")

        for tf in self.graph_time_frames().keys():
            g = Graph(self.image_name(tf),
                      start=int(time.time())-self.graph_time_frames()[tf], end=int(time.time()),
                      lower_limit=0.000001,
                      title='"Ping RTT - Updated {0}"'.format(time.strftime("%Y%m%d at %H:%M")),
                      vertical_label='"RTT - Seconds"',
                      height=self.graph_height, width=self.graph_width,
                      x_grid=self.grid[tf],
                      step=self.graph_step_times[tf])

            g.data.extend([d_avg, d_max, d_min, v_peak, v_avg, v_nadir, area_0])

            if self.graph_time_frames()[tf] > self.graph_time_frames()["1day"] and self.graph_time_frames()[tf] < self.graph_time_frames()["1month"]:
                g.data.extend([l_max])

            if self.graph_time_frames()[tf] > self.graph_time_frames()["1week"]:
                g.data.extend([l_min])

            if self.graph_time_frames()[tf] < self.graph_time_frames()["1month"]:
                g.data.extend([l_peak])

            g.data.extend([p_peak, l_avg, p_avg, l_nadir, p_nadir])
            g.write()

            if False:
                g = Graph(self.icon_name(tf),
                          start=int(time.time())-self.graph_time_frames()[tf], end=int(time.time()),
                          lower_limit=0.000001,
                          no_legend=True,
                          height=self.icon_height, width=self.icon_width,
                          step=self.graph_step_times[tf])
                g.data.extend([d_avg, area_0])
                g.write()
